package it.infodea.tapestrydea.services;

import it.infodea.tapestrydea.services.ClasspathURLConverterJBoss5;
import it.infodea.tapestrydea.services.JcrModule;
import it.infodea.tapestrydea.services.JsWindowsModule;
import it.infodea.tapestrydea.services.PageInfoModule;
import it.infodea.tapestrydea.services.breadcrumb.BreadcrumbService;
import it.infodea.tapestrydea.services.breadcrumb.impl.BreadcrumbServiceImpl;
import it.infodea.tapestrydea.services.pageinfo.PageInfoService;
import it.infodea.tapestrydea.services.pageinfo.impl.PageInfoServiceImpl;

import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.SubModule;
import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
import org.apache.tapestry5.ioc.services.Coercion;
import org.apache.tapestry5.ioc.services.CoercionTuple;
import org.apache.tapestry5.services.LibraryMapping;
import org.slf4j.Logger;

/**
 * This module is automatically included as part of the Tapestry IoC Registry,
 * it's a good place to configure and extend Tapestry, or to place your own
 * service definitions.
 */
@SubModule( { JsWindowsModule.class, JcrModule.class, PageInfoModule.class })
public class TapdeaTestModule {
	//TODO portare tutto in TestModule

	private final Logger logger;

	public TapdeaTestModule(Logger logger) {
		this.logger = logger;
	}

	@SuppressWarnings("unchecked")
	public static void contributeServiceOverride(MappedConfiguration<Class, Object> configuration) {
		configuration.add(ClasspathURLConverter.class, new ClasspathURLConverterJBoss5());
	}

	public static void bind(ServiceBinder binder) {
		binder.bind(BreadcrumbService.class, BreadcrumbServiceImpl.class);
		binder.bind(PageInfoService.class, PageInfoServiceImpl.class);
	}

	public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration) {
		configuration.add(new LibraryMapping("dea", "it.infodea.tapestrydea"));
		configuration.add(new LibraryMapping("", "it.infodea.tapestrydea"));
	}

	public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration) {
		configuration.add("dea.jsscripts", "classpath:it/infodea/tapestrydea/assets/scripts/");
	}

	public void contributeTypeCoercer(Configuration<CoercionTuple> configuration) {
		//TODO Serve???
		add(configuration, String.class, Class.class, new Coercion<String, Class>() {

			public Class coerce(String input) {
				try {
					return Class.forName(input);
				} catch (ClassNotFoundException e) {
					// TODO [Marco]: migliorare il messaggio
					logger.warn(e.getMessage());
				}
				return null;
			}
		});
		add(configuration, String.class, String[].class, new Coercion<String, String[]>() {

			public String[] coerce(String input) {
				return input != null ? input.split(",") : new String[0];
			}
		});
	}

	private static <S, T> void add(Configuration<CoercionTuple> configuration, Class<S> sourceType, Class<T> targetType,
			Coercion<S, T> coercion) {
		//TODO Serve???
		CoercionTuple<S, T> tuple = new CoercionTuple<S, T>(sourceType, targetType, coercion);

		configuration.add(tuple);
	}

}
